<template>
  <div class="max-w-4xl mx-auto p-6">
    <div class="flex items-center justify-between mb-6">
      <div>
        <h1 class="text-2xl font-semibold">图片取色器</h1>
        <p class="mt-1 text-sm text-gray-600">上传图片后点击图片任意处以获取该点颜色，支持保存调色板与导出。</p>
      </div>
      <NuxtLink to="/image-tools" class="text-blue-500 text-sm">返回图片工具</NuxtLink>
    </div>

    <div class="mb-4 p-4 bg-gray-50 border border-gray-200 rounded">
      <h2 class="text-lg font-medium mb-2">使用说明</h2>
      <ol class="list-decimal list-inside text-sm text-gray-700 space-y-1 mb-2">
        <li>点击“选择图片”或将图片拖拽到上传区域加载图片（仅支持本地读取）。</li>
        <li>在图片上点击或触摸任意位置，取色器会读取该点像素并显示 HEX 与 RGB 值。</li>
        <li>点击“复制 HEX”将当前颜色复制到剪贴板；若被禁用请允许页面使用剪贴板权限。</li>
        <li>点击“保存”将当前颜色加入调色板，最多保存 40 个颜色；可导出为文本文件或清空调色板。</li>
        <li>调色板保存在本地浏览器的 LocalStorage 中，刷新或关闭浏览器后仍可恢复（仅在同一设备/同一浏览器）。</li>
      </ol>
      <h3 class="text-sm font-medium mb-1">注意事项</h3>
      <ul class="list-disc list-inside text-sm text-gray-700 space-y-1">
        <li>如果图片来自远程 URL 且存在跨域限制，取色可能失败，请优先使用本地文件或允许 CORS。</li>
        <li>在高 DPI 屏幕或缩放情况下，鼠标坐标会按画布实际像素比例进行转换以保证取色准确。</li>
        <li>为保护隐私，图片不会被上传到服务器，所有处理均在本地完成。</li>
        <li>若导出/复制功能不可用，请检查浏览器设置或在最新版本的浏览器中重试。</li>
      </ul>
    </div>

    <!-- Upload area -->
    <div
      @dragover.prevent
      @drop.prevent="onDrop"
      class="border-2 border-dashed border-gray-200 rounded-lg p-6 mb-6 text-center bg-white"
    >
      <div class="flex items-center justify-center space-x-4">
        <input ref="fileInput" type="file" accept="image/*" @change="onFileChange" class="hidden" />
        <button @click="openFile" class="primary-button">选择图片</button>
        <span class="text-sm text-gray-500">或将图片拖拽到此处</span>
      </div>
      <p v-if="imageName" class="mt-3 text-sm text-gray-600">已加载: {{ imageName }}</p>
    </div>

    <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
      <!-- Canvas / Image preview -->
      <div class="col-span-2 bg-white p-4 rounded-lg">
        <div class="mb-3 text-sm text-gray-500">点击图片以拾取颜色（支持触摸）</div>
        <div class="overflow-auto">
          <canvas
            ref="canvas"
            @click="onCanvasClick"
            @touchstart.prevent="onTouchStart"
            class="max-w-full h-auto rounded"
            style="background:#f8fafc"
          ></canvas>
        </div>
        <div v-if="!hasImage" class="mt-4 text-gray-500 text-sm">尚未加载图片</div>
      </div>

      <!-- Controls and palette -->
      <div class="bg-white p-4 rounded-lg">
        <div class="mb-4">
          <div class="flex items-center space-x-3">
            <div class="w-12 h-12 rounded border flex items-center justify-center" :style="{ background: currentHex || '#ffffff' }"></div>
            <div class="flex-1">
              <div class="font-medium">当前颜色</div>
              <div class="text-sm text-gray-600">{{ displayColor }}</div>
            </div>
          </div>
          <div class="mt-3 flex space-x-2">
            <button @click="copyColor" :disabled="!currentHex" class="primary-button flex-1">复制 HEX</button>
            <button @click="addToPalette" :disabled="!currentHex" class="border px-3 py-2 rounded">保存</button>
          </div>
        </div>

        <div>
          <div class="flex items-center justify-between mb-2">
            <div class="font-medium">调色板</div>
            <div class="text-sm text-gray-500">已保存 {{ palette.length }} 个</div>
          </div>

          <div v-if="palette.length === 0" class="text-sm text-gray-500">尚无颜色，点击“保存”将当前颜色加入调色板。</div>
          <div class="mt-2 grid grid-cols-5 gap-2">
            <div v-for="(c, i) in palette" :key="i" class="flex flex-col items-center">
              <div :style="{ background: c }" class="w-12 h-12 rounded border"></div>
              <div class="text-xs mt-1">{{ c }}</div>
            </div>
          </div>

          <div class="mt-4 flex space-x-2">
            <button @click="exportPalette" :disabled="palette.length===0" class="primary-button flex-1">导出调色板</button>
            <button @click="clearPalette" :disabled="palette.length===0" class="border px-3 py-2 rounded">清空</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, computed } from 'vue'

useHead({ title: '图片取色器 - 图片工具' })

const canvas = ref(null)
const fileInput = ref(null)
const imageName = ref('')
const hasImage = ref(false)
const currentHex = ref('')
const currentRgb = ref('')
const palette = ref([])

// load palette from localStorage
try {
  const raw = localStorage.getItem('colorPicker.palette')
  if (raw) palette.value = JSON.parse(raw)
} catch (e) {
  // ignore
}

function savePaletteToStorage() {
  try { localStorage.setItem('colorPicker.palette', JSON.stringify(palette.value)) } catch (e) {}
}

function openFile() {
  if (fileInput.value && fileInput.value.click) fileInput.value.click()
}

function onFileChange(e) {
  const f = e.target.files && e.target.files[0]
  if (f) loadImageFile(f)
}

function onDrop(e) {
  const f = e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files[0]
  if (f) loadImageFile(f)
}

function loadImageFile(file) {
  if (!file.type.startsWith('image/')) return
  imageName.value = file.name
  const reader = new FileReader()
  reader.onload = () => {
    const img = new Image()
    img.onload = () => drawImageToCanvas(img)
    img.src = reader.result
  }
  reader.readAsDataURL(file)
}

function drawImageToCanvas(img) {
  const c = canvas.value
  if (!c) return
  const ctx = c.getContext('2d')
  // set canvas to image natural size for accurate pixel reading
  c.width = img.naturalWidth || img.width
  c.height = img.naturalHeight || img.height
  // clear and draw
  ctx.clearRect(0, 0, c.width, c.height)
  ctx.drawImage(img, 0, 0, c.width, c.height)
  hasImage.value = true
}

function getColorAtPoint(clientX, clientY) {
  const c = canvas.value
  if (!c) return null
  const rect = c.getBoundingClientRect()
  const scaleX = c.width / rect.width
  const scaleY = c.height / rect.height
  const x = Math.floor((clientX - rect.left) * scaleX)
  const y = Math.floor((clientY - rect.top) * scaleY)
  const ctx = c.getContext('2d')
  const data = ctx.getImageData(x, y, 1, 1).data
  const [r, g, b, a] = data
  const hex = rgbToHex(r, g, b)
  currentHex.value = hex
  currentRgb.value = `rgb(${r}, ${g}, ${b})`
}

function onCanvasClick(ev) {
  if (!hasImage.value) return
  getColorAtPoint(ev.clientX, ev.clientY)
}

function onTouchStart(ev) {
  if (!hasImage.value) return
  const t = ev.touches[0]
  if (t) getColorAtPoint(t.clientX, t.clientY)
}

function rgbToHex(r, g, b) {
  return '#' + [r, g, b].map(n => n.toString(16).padStart(2, '0')).join('').toUpperCase()
}

function copyColor() {
  if (!currentHex.value) return
  navigator.clipboard.writeText(currentHex.value)
}

function addToPalette() {
  if (!currentHex.value) return
  if (!palette.value.includes(currentHex.value)) {
    palette.value.unshift(currentHex.value)
    // limit to 40
    if (palette.value.length > 40) palette.value.pop()
    savePaletteToStorage()
  }
}

function clearPalette() {
  palette.value = []
  savePaletteToStorage()
}

function exportPalette() {
  const content = palette.value.join('\n')
  const blob = new Blob([content], { type: 'text/plain;charset=utf-8' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = 'palette.txt'
  document.body.appendChild(a)
  a.click()
  a.remove()
  URL.revokeObjectURL(url)
}

const displayColor = computed(() => currentHex.value ? `${currentHex.value} · ${currentRgb.value}` : '（未选择）')

onMounted(() => {
  // no-op
})
</script>

<style scoped>
.primary-button {
  background-color: #2563eb; /* bg-blue-600 */
  color: #ffffff;
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
.primary-button:hover {
  background-color: #1e40af; /* bg-blue-700 */
}
</style>
